﻿using System;
using System.Text;
using Zo.Tasks;

namespace Zo.Logging
{
    /// <summary>
    /// 日志记录器。
    /// </summary>
    public interface ILogger
    {
        /// <summary>
        /// 日志等级。
        /// </summary>
        LogLevel Level { get; }

        /// <summary>
        /// 设置日志等级。
        /// </summary>
        /// <param name="level">日志等级。</param>
        void SetLevel(LogLevel level);

        /// <summary>
        /// 错误信息。
        /// </summary>
        /// <param name="message">日志信息。</param>
        /// <param name="functionType">日志分类。</param>
        /// <param name="exception">异常信息。</param>
        void LogError(string message, string functionType = "", Exception exception = null);

        /// <summary>
        /// 致命错误。
        /// </summary>
        /// <param name="message">日志信息。</param>
        /// <param name="functionType">日志分类。</param>
        /// <param name="exception">异常信息。</param>
        void Fatal(string message, string functionType = "", Exception exception = null);

        /// <summary>
        /// 调试日志信息。
        /// </summary>
        /// <param name="message">日志信息。</param>
        /// <param name="functionType">日志分类。</param>
        /// <param name="exception">异常信息。</param>
        void Debug(string message, string functionType = "", Exception exception = null);

        /// <summary>
        /// 警告日志信息。
        /// </summary>
        /// <param name="message">日志信息。</param>
        /// <param name="functionType">日志分类。</param>
        /// <param name="exception">异常信息。</param>
        void LogWarning(string message, string functionType = "", Exception exception = null);

        /// <summary>
        /// 普通日志信息。
        /// </summary>
        /// <param name="message">日志信息。</param>
        void LogInfo(string message);
    }

    public abstract class LoggerBase : ILogger
    {
        public LogLevel Level { get; private set; }

        public virtual void SetLevel(LogLevel level)
        {
            Level = level;
        }

        public virtual void Debug(string message, string functionType = "", Exception exception = null)
        {
            if (Level == LogLevel.All)
            {
                WriteLog(BuildMessage(message, functionType, exception), functionType, "DEBUG");
            }
        }

        public virtual void Fatal(string message, string functionType = "", Exception exception = null)
        {
            if (Level == LogLevel.All || Level == LogLevel.NormalAndError || Level == LogLevel.Error)
            {
                WriteLog(BuildMessage(message, functionType, exception), functionType, "FATAL");
            }
        }

        public virtual void LogError(string message, string functionType = "", Exception exception = null)
        {
            if (Level == LogLevel.All || Level == LogLevel.NormalAndError || Level == LogLevel.Error)
            {
                WriteLog(BuildMessage(message, functionType, exception), functionType, "ERROR");
            }
        }

        public virtual void LogWarning(string message, string functionType = "", Exception exception = null)
        {
            if (Level == LogLevel.All || Level == LogLevel.NormalAndError || Level == LogLevel.Error)
            {
                WriteLog(BuildMessage(message, functionType, exception), functionType, "WARNING");
            }
        }

        public void LogInfo(string message)
        {
            message = message ?? string.Empty;

            Console.WriteLine(message);

            WriteLog(message, "", "INFO");
        }

        protected virtual string BuildMessage(string message, string functionType = "", Exception exception = null)
        {
            var messageBuilder = new StringBuilder();

            if (exception != null)
            {
                messageBuilder.AppendLine($"#-------------------------日志消息-------------------------#");
                messageBuilder.AppendLine($"记录时间：{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff")}");
                messageBuilder.AppendLine(message);
                messageBuilder.AppendLine($"#-------------------------日志消息-------------------------#");
                messageBuilder.AppendLine($"#-------------------------异常信息-------------------------#");
                messageBuilder.AppendLine($"{exception.StackTrace}");
                messageBuilder.AppendLine($"#-------------------------异常信息-------------------------#");
            }
            else
            {
                messageBuilder.AppendLine($"#-------------------------日志消息-------------------------#");
                messageBuilder.AppendLine($"记录时间：{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff")}");
                messageBuilder.AppendLine(message);
                messageBuilder.AppendLine($"#-------------------------日志消息-------------------------#");
            }

            messageBuilder.AppendLine();

            return messageBuilder.ToString();
        }

        protected abstract void WriteLog(string message, string functionType, string logType);
    }
}